﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Cos.Core.Model.Common;
using Cos.Core.Model.Form;
using Cos.Core.NHibernate;
using Cos.Module.Form.Data;
using Cos.Module.Form.Exceptions;
using NHibernate;
using NHibernate.Criterion;

namespace Cos.Module.Form.NHibernate
{
    public class FormRepository : RepositoryBase, IFormRepository
    {
        public FormRepository(ISessionFactory sessionFactory)
            : base(sessionFactory)
        {
        }

        public Core.Model.Form.Form GetForm(int formId, Culture culture, bool isLiveMode)
        {
            // Get the data from the database
            var form = this.CurrentSession.Get<FormDataModel>(formId);
            if (form == null)
            {
                throw new FormNotFoundException("Not such form in the database. Form.ID: " + formId);
            }

            var cultureModel = this.CurrentSession.Get<CultureDataModel>(culture.CultureCode);
            if (cultureModel == null)
            {
                throw new FormNotFoundException("Not such form in the database. Culture.CultureCode: " + culture.CultureCode);
            }

            // Convert the form into a FormVo
            // TODO return FormModelToVoConverter.convertToFormVo(form, cultureModel, isLiveMode);
            throw new NotImplementedException();
        }

        public Core.Model.Form.Form GetForm(int formId, int cultureId, bool isLiveMode)
        {
            // Get the data from the database
            var form = this.CurrentSession.Get<FormDataModel>(formId);
            if (form == null)
            {
                throw new FormNotFoundException("Not such form in the database. Form.ID: " + formId);
            }

            var cultureModel = this.CurrentSession.Get<CultureDataModel>(cultureId);
            if (cultureModel == null)
            {
                throw new FormNotFoundException("Not such form in the database. Culture.CultureID: " + cultureId);
            }

            // Convert the form into a FormVo
            // TODO return FormModelToVoConverter.convertToFormVo(form, culture, isLiveMode);
            throw new NotImplementedException();
        }

        public Core.Model.Form.Form GetForm(int formId, string cultureCode, bool isLiveMode)
        {
            // Get the data from the database
            var form = this.CurrentSession.Get<FormDataModel>(formId);
            if (form == null)
            {
                throw new FormNotFoundException("Not such form in the database. Form.ID: " + formId);
            }

            var culture = this.CurrentSession.CreateCriteria<CultureDataModel>().Add(Restrictions.Eq("cultureCode", cultureCode)).UniqueResult<CultureDataModel>();
            if (culture == null)
            {
                throw new FormNotFoundException("Not such form in the database. Culture.CultureCode: " + cultureCode);
            }

            // Convert the form into a FormVo
            // TODO return FormModelToVoConverter.convertToFormVo(form, culture, isLiveMode);
            throw new NotImplementedException();
        }

        public IDictionary<string, int> GetAnswerCount(int formElement)
        {
            var query = this.CurrentSession.CreateSQLQuery(
                "SELECT CAST(fec.Value AS varchar), COUNT(svi.ID) AS res FROM " + "Form_Element_Choice AS fec JOIN "
                        + "Submission_Value AS sv ON fec.Form_Element_ID = sv.Form_Element_ID JOIN "
                        + "Submission_Value_Item AS svi ON sv.ID = svi.Submission_Value_ID AND fec.Value = svi.Value " + "WHERE " + "fec.Form_Element_ID = :formElementId "
                        + "GROUP BY " + "fec.Value");
            query.SetInt32("formElementId", formElement);

            var results = query.List<object[]>();

            return results.ToDictionary(o => (string)o[0], o => (int)o[1]);
        }

        public void SubmitForm(BasicCameleonFormSubmission submission, bool isLiveMode, string generator)
        {
            if (submission == null)
            {
                throw new InvalidOperationException("The submission is null");
            }

            // Get the dependent objects from the data base
            var culture = this.CurrentSession.Get<CultureDataModel>(submission.CultureCode);
            var form = this.CurrentSession.Get<FormDataModel>(submission.FormId);

            if (culture == null)
            {
                throw new InvalidOperationException("The culture id " + submission.CultureCode + " doesn't exist in the database");
            }
            else if (form == null)
            {
                throw new InvalidOperationException("The form id " + submission.FormId + " doesn't exist in the database");
            }

            // TODO Submission submissionModel = SubmissionBeanToModelConverter.convertBeanToModel(submission, form, culture);
            // TODO getHibernateTemplate().save(submissionModel);
            throw new NotImplementedException();
        }

        public Cos.Core.Model.Form.Form CreateForm(Culture culture)
        {
            throw new NotImplementedException();
        }

        public void UpdateForm(Cos.Core.Model.Form.Form form)
        {
            this.CurrentSession.Update(form);
        }

        public void DeleteForm(Cos.Core.Model.Form.Form form)
        {
            this.CurrentSession.Delete(form);
        }

        public Cos.Core.Model.Form.Page GetPage(int id, Culture culture)
        {
            var page = CurrentSession.Get<PageDataModel>(id).ToModel();
            //?!
            throw new NotImplementedException();
        }

        public IEnumerable<Cos.Core.Model.Form.Page> GetPages(int formId, Culture culture)
        {
            //var form=this.CurrentSession
            throw new NotImplementedException();
        }

        public Cos.Core.Model.Form.Page CreatePage(Cos.Core.Model.Form.Form form, Culture culture)
        {
            throw new NotImplementedException();
        }

        public void UpdatePage(Cos.Core.Model.Form.Page page)
        {
            this.CurrentSession.Update(page);
        }

        public void DeletePage(Cos.Core.Model.Form.Page page)
        {
            this.CurrentSession.Delete(page);
        }

        public Cos.Core.Model.Form.Element GetElement(int id, Culture culture)
        {
            throw new NotImplementedException();
        }

        public IEnumerable<Cos.Core.Model.Form.Element> GetElements(int formId, Culture culture)
        {
            throw new NotImplementedException();
        }

        public Cos.Core.Model.Form.Element CreateElement(Cos.Core.Model.Form.Page page, Culture culture)
        {
            throw new NotImplementedException();
        }

        public void UpdateElement(Cos.Core.Model.Form.Element element)
        {
            this.CurrentSession.Update(element);
        }

        public void DeleteElement(Cos.Core.Model.Form.Element element)
        {
            throw new NotImplementedException();
        }

        public Cos.Core.Model.Form.Choice GetChoice(int id, Culture culture)
        {
            throw new NotImplementedException();
        }

        public IEnumerable<Cos.Core.Model.Form.Choice> GetChoices(int elementId, Culture culture)
        {
            throw new NotImplementedException();
        }

        public Cos.Core.Model.Form.Choice CreateChoice(Cos.Core.Model.Form.Element element, Culture culture)
        {
            throw new NotImplementedException();
        }

        public void UpdateChoice(Cos.Core.Model.Form.Choice choice)
        {
            this.CurrentSession.Update(choice);
        }

        public void DeleteChoice(Cos.Core.Model.Form.Choice choice)
        {
            this.CurrentSession.Delete(choice);
        }

        public Cos.Core.Model.Form.Submission GetSubmission(int id)
        {
            throw new NotImplementedException();
        }

        public IEnumerable<Cos.Core.Model.Form.Submission> GetSubmissions(int formId)
        {
            throw new NotImplementedException();
        }

        public IEnumerable<Cos.Core.Model.Form.Submission> GetSubmissions(int formId, Culture culture, DateTime? startDate, DateTime? endDate, string pageUrl)
        {
            throw new NotImplementedException();
        }

        public Cos.Core.Model.Form.Submission CreateSubmission(int formId, Culture culture)
        {
            throw new NotImplementedException();
        }

        public void UpdateSubmission(Cos.Core.Model.Form.Submission submission)
        {
            this.CurrentSession.Update(submission);
        }

        public Cos.Core.Model.Form.SubmissionValue GetSubmissionValue(int id)
        {
            throw new NotImplementedException();
        }

        public IEnumerable<Cos.Core.Model.Form.SubmissionValue> GetSubmissionValues(int submissionId)
        {
            throw new NotImplementedException();
        }

        public Cos.Core.Model.Form.SubmissionValue CreateSubmissionValue(int submissionId)
        {
            throw new NotImplementedException();
        }

        public void UpdateSubmissionValue(Cos.Core.Model.Form.SubmissionValue value)
        {
            this.CurrentSession.Update(value);
        }

        public Cos.Core.Model.Form.SubmissionValueItem GetSubmissionValueItem(int id)
        {
            throw new NotImplementedException();
        }

        public IEnumerable<Cos.Core.Model.Form.SubmissionValueItem> GetSubmissionValueItems(int submissionValueId)
        {
            throw new NotImplementedException();
        }

        public Cos.Core.Model.Form.SubmissionValueItem CreateSubmissionValueItem(int submissionValueId)
        {
            throw new NotImplementedException();
        }

        public void UpdateSubmissionValueItem(Cos.Core.Model.Form.SubmissionValueItem item)
        {
            this.CurrentSession.Update(item);
        }
    }
}
